home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.001 / tcpdump-~ / tcpdump-3.0.2-linux / libpcap-0.0.6 / pcap-snit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-22  |  6.9 KB  |  294 lines

  1. /*
  2.  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. static  char rcsid[] =
  23.     "@(#)$Header: pcap-snit.c,v 1.33+ 94/06/23 13:51:17 leres Exp $ (LBL)";
  24. #endif
  25.  
  26. /*
  27.  * Modifications made to accomodate the new SunOS4.0 NIT facility by
  28.  * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989.
  29.  * This module now handles the STREAMS based NIT.
  30.  */
  31.  
  32. #include <sys/types.h>
  33. #include <sys/time.h>
  34. #include <sys/timeb.h>
  35. #include <sys/dir.h>
  36. #include <sys/fcntlcom.h>
  37. #include <sys/file.h>
  38. #include <sys/ioctl.h>
  39. #include <sys/socket.h>
  40. #include <sys/stropts.h>
  41.  
  42. #include <net/bpf.h>
  43. #include <net/if.h>
  44. #include <net/nit.h>
  45. #include <net/nit_if.h>
  46. #include <net/nit_pf.h>
  47. #include <net/nit_buf.h>
  48.  
  49. #include <netinet/in.h>
  50. #include <netinet/in_systm.h>
  51. #include <netinet/ip.h>
  52. #include <netinet/if_ether.h>
  53. #include <netinet/ip_var.h>
  54. #include <netinet/udp.h>
  55. #include <netinet/udp_var.h>
  56. #include <netinet/tcp.h>
  57. #include <netinet/tcpip.h>
  58.  
  59. #include <ctype.h>
  60. #include <errno.h>
  61. #include <stdio.h>
  62. #include <string.h>
  63.  
  64. #include "pcap-int.h"
  65.  
  66. /*
  67.  * The chunk size for NIT.  This is the amount of buffering
  68.  * done for read calls.
  69.  */
  70. #define CHUNKSIZE (2*1024)
  71.  
  72. /*
  73.  * The total buffer space used by NIT.
  74.  */
  75. #define BUFSPACE (4*CHUNKSIZE)
  76.  
  77. /* Forwards */
  78. static int nit_setflags(int, int, int, char *);
  79.  
  80. int
  81. pcap_stats(pcap_t *p, struct pcap_stat *ps)
  82. {
  83.  
  84.     *ps = p->md.stat;
  85.     return (0);
  86. }
  87.  
  88. int
  89. pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  90. {
  91.     register int cc, n;
  92.     register struct bpf_insn *fcode = p->fcode.bf_insns;
  93.     register u_char *bp, *cp, *ep;
  94.     register struct nit_bufhdr *hdrp;
  95.     register struct nit_iftime *ntp;
  96.     register struct nit_iflen *nlp;
  97.     register struct nit_ifdrops *ndp;
  98.     register int caplen;
  99.  
  100.     cc = p->cc;
  101.     if (cc == 0) {
  102.         cc = read(p->fd, (char *)p->buffer, p->bufsize);
  103.         if (cc < 0) {
  104.             if (errno == EWOULDBLOCK)
  105.                 return (0);
  106.             sprintf(p->errbuf, "pcap_read: %s",
  107.                 pcap_strerror(errno));
  108.             return (-1);
  109.         }
  110.         bp = p->buffer;
  111.     } else
  112.         bp = p->bp;
  113.  
  114.     /*
  115.      * loop through each snapshot in the chunk
  116.      */
  117.     n = 0;
  118.     ep = bp + cc;
  119.     while (bp < ep) {
  120.         ++p->md.stat.ps_recv;
  121.         cp = bp;
  122.  
  123.         /* get past NIT buffer  */
  124.         hdrp = (struct nit_bufhdr *)cp;
  125.         cp += sizeof(*hdrp);
  126.  
  127.         /* get past NIT timer   */
  128.         ntp = (struct nit_iftime *)cp;
  129.         cp += sizeof(*ntp);
  130.  
  131.         ndp = (struct nit_ifdrops *)cp;
  132.         p->md.stat.ps_drop = ndp->nh_drops;
  133.         cp += sizeof *ndp;
  134.  
  135.         /* get past packet len  */
  136.         nlp = (struct nit_iflen *)cp;
  137.         cp += sizeof(*nlp);
  138.  
  139.         /* next snapshot        */
  140.         bp += hdrp->nhb_totlen;
  141.  
  142.         caplen = nlp->nh_pktlen;
  143.         if (caplen > p->snapshot)
  144.             caplen = p->snapshot;
  145.  
  146.         if (bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) {
  147.             struct pcap_pkthdr h;
  148.             h.ts = ntp->nh_timestamp;
  149.             h.len = nlp->nh_pktlen;
  150.             h.caplen = caplen;
  151.             (*callback)(user, &h, cp);
  152.             if (++n >= cnt && cnt >= 0) {
  153.                 p->cc = ep - bp;
  154.                 p->bp = bp;
  155.                 return (n);
  156.             }
  157.         }
  158.     }
  159.     p->cc = 0;
  160.     return (n);
  161. }
  162.  
  163. static int
  164. nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
  165. {
  166.     u_long flags;
  167.     struct strioctl si;
  168.     struct timeval timeout;
  169.  
  170.     si.ic_timout = INFTIM;
  171.     if (to_ms != 0) {
  172.         timeout.tv_sec = to_ms / 1000;
  173.         timeout.tv_usec = (to_ms * 1000) % 1000000;
  174.         si.ic_cmd = NIOCSTIME;
  175.         si.ic_len = sizeof(timeout);
  176.         si.ic_dp = (char *)&timeout;
  177.         if (ioctl(fd, I_STR, (char *)&si) < 0) {
  178.             sprintf(ebuf, "NIOCSTIME: %s", pcap_strerror(errno));
  179.             return (-1);
  180.         }
  181.     }
  182.     flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
  183.     if (promisc)
  184.         flags |= NI_PROMISC;
  185.     si.ic_cmd = NIOCSFLAGS;
  186.     si.ic_len = sizeof(flags);
  187.     si.ic_dp = (char *)&flags;
  188.     if (ioctl(fd, I_STR, (char *)&si) < 0) {
  189.         sprintf(ebuf, "NIOCSFLAGS: %s", pcap_strerror(errno));
  190.         return (-1);
  191.     }
  192.     return (0);
  193. }
  194.  
  195. pcap_t *
  196. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  197. {
  198.     struct strioctl si;        /* struct for ioctl() */
  199.     struct ifreq ifr;        /* interface request struct */
  200.     int chunksize = CHUNKSIZE;
  201.     int fd;
  202.     static char dev[] = "/dev/nit";
  203.     register pcap_t *p;
  204.  
  205.     p = (pcap_t *)malloc(sizeof(*p));
  206.     if (p == NULL) {
  207.         strcpy(ebuf, pcap_strerror(errno));
  208.         return (NULL);
  209.     }
  210.  
  211.     if (snaplen < 96)
  212.         /*
  213.          * NIT requires a snapshot length of at least 96.
  214.          */
  215.         snaplen = 96;
  216.  
  217.     bzero(p, sizeof(*p));
  218.     p->fd = fd = open(dev, O_RDONLY);
  219.     if (fd < 0) {
  220.         sprintf(ebuf, "%s: %s", dev, pcap_strerror(errno));
  221.         goto bad;
  222.     }
  223.  
  224.     /* arrange to get discrete messages from the STREAM and use NIT_BUF */
  225.     if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
  226.         sprintf(ebuf, "I_SRDOPT: %s", pcap_strerror(errno));
  227.         goto bad;
  228.     }
  229.     if (ioctl(fd, I_PUSH, "nbuf") < 0) {
  230.         sprintf(ebuf, "push nbuf: %s", pcap_strerror(errno));
  231.         goto bad;
  232.     }
  233.     /* set the chunksize */
  234.     si.ic_cmd = NIOCSCHUNK;
  235.     si.ic_timout = INFTIM;
  236.     si.ic_len = sizeof(chunksize);
  237.     si.ic_dp = (char *)&chunksize;
  238.     if (ioctl(fd, I_STR, (char *)&si) < 0) {
  239.         sprintf(ebuf, "NIOCSCHUNK: %s", pcap_strerror(errno));
  240.         goto bad;
  241.     }
  242.  
  243.     /* request the interface */
  244.     strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  245.     ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
  246.     si.ic_cmd = NIOCBIND;
  247.     si.ic_len = sizeof(ifr);
  248.     si.ic_dp = (char *)𝔦
  249.     if (ioctl(fd, I_STR, (char *)&si) < 0) {
  250.         sprintf(ebuf, "NIOCBIND: %s: %s",
  251.             ifr.ifr_name, pcap_strerror(errno));
  252.         goto bad;
  253.     }
  254.  
  255.     /* set the snapshot length */
  256.     si.ic_cmd = NIOCSSNAP;
  257.     si.ic_len = sizeof(snaplen);
  258.     si.ic_dp = (char *)&snaplen;
  259.     if (ioctl(fd, I_STR, (char *)&si) < 0) {
  260.         sprintf(ebuf, "NIOCSSNAP: %s", pcap_strerror(errno));
  261.         goto bad;
  262.     }
  263.     p->snapshot = snaplen;
  264.     if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 0)
  265.         goto bad;
  266.  
  267.     (void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
  268.     /*
  269.      * NIT supports only ethernets.
  270.      */
  271.     p->linktype = DLT_EN10MB;
  272.  
  273.     p->bufsize = BUFSPACE;
  274.     p->buffer = (u_char *)malloc(p->bufsize);
  275.     if (p->buffer == NULL) {
  276.         strcpy(ebuf, pcap_strerror(errno));
  277.         goto bad;
  278.     }
  279.     return (p);
  280.  bad:
  281.     if (fd >= 0)
  282.         close(fd);
  283.     free(p);
  284.     return (NULL);
  285. }
  286.  
  287. int
  288. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  289. {
  290.  
  291.     p->fcode = *fp;
  292.     return (0);
  293. }
  294.